home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / archiver / restore.arc / RESTORE.C < prev    next >
C/C++ Source or Header  |  1988-01-07  |  12KB  |  387 lines

  1. /*
  2.  *----------------------------------------------------------------------------
  3.  *
  4.  *    RESTORE.C : a backup restorer for the Atari ST series
  5.  *
  6.  *    This code was written to complement the very useful `Turtle'
  7.  *    hard disk backup utility.  It essentially does a `cp -r', maintaining
  8.  *    the time stamps on files.  It will create directories as needed
  9.  *    on the receiving filesystem.
  10.  *
  11.  *    This code is copyright (C) by Ross Alexander, Athabasca University,
  12.  *    1988.  It may be freely redistributed and/or modified as long as:
  13.  *        1) This notice appears, &
  14.  *        2) modifications are noted as NOT my work.
  15.  *
  16.  *    I think this programme is OK, but I take no responsibility for
  17.  *    any result (or lack thereof...) of using it.  Caveat Emptor.
  18.  *
  19.  *    Basic Algorithm:
  20.  *
  21.  *        open source directory
  22.  *        count entries, reserve that much memory
  23.  *        reopen source directory, read into memory
  24.  *        sort alphabetically, moving directories to head
  25.  *            of the list.
  26.  *        conditionally create target directory
  27.  *        call self for all directories in list
  28.  *        copy all files in list to target, correcting time stamps
  29.  *        release memory for list
  30.  *
  31.  *----------------------------------------------------------------------------
  32.  */
  33.  
  34. #include        <osbind.h>
  35. #include        <stat.h>
  36. #include        <stdio.h>
  37. #include    <ctype.h>
  38.  
  39. #define         CANDIDATES  ( S_IJRON | S_IJHID | S_IJSYS | S_IJDIR | S_IJWAC )
  40. #define         NULLPTR     ( (char *) 0 )
  41.  
  42. extern char     * malloc();
  43. extern char    * strcpy();
  44.  
  45. /*  this is the stuff at the end of a DMABUFFER                             */
  46.  
  47. typedef struct {
  48.     char            f_fattr;    /* File attributes */
  49.     long            f_tandd;    /* Time and date words */
  50.     long            f_fsize;    /* File size */
  51.     char            f_fname[14];    /* File name */
  52. }               FILEINFO;
  53.  
  54. /*  this is a big enough buffer to do most files in a gulp                  */
  55.  
  56. #define        BUFFER_SIZE    16384    /* utterly arbitrary            */
  57. char            track_buffer[ BUFFER_SIZE ];
  58.  
  59. int        v_flag = 0;    /* verbosity flag                */
  60.  
  61. /*
  62.  *----------------------------------------------------------------------------
  63.  *
  64.  *  make a (longer) path name from a path-name and {dir,file}-name components
  65.  *
  66.  *----------------------------------------------------------------------------
  67.  */
  68.  
  69. char * dircat( path, name )
  70.     char            * path;
  71.     char            * name;
  72.     {
  73.     int             path_len    = strlen( path );
  74.     char            path_buf[ 128 ];    /* _should_ be lots...              */
  75.     char        * scan = path_buf;
  76.  
  77.     strcpy( path_buf, path );
  78.     if ( path_len != 0 && path[ path_len - 1 ] != '\\' )
  79.         strcat( path_buf, "\\" );
  80.     strcat( path_buf, name );
  81.  
  82.     while ( * scan ) {
  83.     if ( isupper( * scan ) ) * scan = tolower( * scan );
  84.     ++ scan;
  85.     }
  86.  
  87.     return strcpy( malloc( strlen( path_buf ) + 1 ), path_buf );
  88. }
  89.  
  90. /*
  91.  *----------------------------------------------------------------------------
  92.  *
  93.  *  count how many entries exist in a directory.  ignores volume labels, ., ..
  94.  *
  95.  *----------------------------------------------------------------------------
  96.  */
  97.  
  98. int get_dir_size( from )
  99.     char        * from;        /* source pathname            */
  100.     {
  101.     DMABUFFER       examine;            /* place to hold these for counting */
  102.     int             status;             /* temp to hold Fs{first|next} value*/
  103.     DMABUFFER       * old_dta   = (DMABUFFER *) Fgetdta();
  104.     char            * globname  = dircat( from, "*.*" );
  105.     int             list_length = 0;
  106.  
  107.     Fsetdta( & examine );               /* read'em here, avoid buss faults! */
  108.     for ( status = Fsfirst( globname, CANDIDATES );
  109.             status == 0;
  110.                 status = Fsnext() )
  111.         if ( examine.d_fname[ 0 ] != '.' )
  112.             ++ list_length;             /* ignore ., ..                     */
  113.  
  114.     Fsetdta( old_dta );
  115.     free( globname );                   /* don't need this any more         */
  116.  
  117.     return list_length;
  118. }
  119.  
  120. /*
  121.  *----------------------------------------------------------------------------
  122.  *
  123.  *  compare two directory entries; subdirectories sort ahead of files
  124.  *
  125.  *----------------------------------------------------------------------------
  126.  */
  127.  
  128. static int dir_comp( a, b )
  129.     FILEINFO        * a;
  130.     FILEINFO        * b;
  131.     {
  132.     int             attr_a = a->f_fattr & S_IJDIR;
  133.     int             attr_b = b->f_fattr & S_IJDIR;
  134.  
  135.     if ( attr_a != attr_b )
  136.         return attr_a ? -1 : 1;         /* directories-ahead-of-files       */
  137.     else
  138.         return strcmp( a->f_fname, b->f_fname );
  139. }
  140.  
  141. /*
  142.  *----------------------------------------------------------------------------
  143.  *
  144.  *  suck in a directory, sort it, return -> entries
  145.  *
  146.  *----------------------------------------------------------------------------
  147.  */
  148.  
  149. FILEINFO * read_sorted_dir( path, length )
  150.     char            * path;
  151.     int             length;
  152.     {
  153.     FILEINFO        * list      = (FILEINFO *) malloc( length * sizeof (FILEINFO) );
  154.     FILEINFO        * scan      = list;
  155.     char            * globname  = dircat( path, "*.*" );
  156.     DMABUFFER       * old_dta   = (DMABUFFER *) Fgetdta();
  157.     DMABUFFER       examine;
  158.     int             status;
  159.  
  160.     Fsetdta( & examine );               /* read'em here, avoid buss faults! */
  161.     for ( status = Fsfirst( globname, CANDIDATES );
  162.             status == 0;
  163.                 status = Fsnext() )
  164.         if ( examine.d_fname[ 0 ] != '.' ) {
  165.             scan->f_fattr = examine.d_fattr;
  166.             scan->f_tandd = examine.d_tandd;
  167.             scan->f_fsize = examine.d_fsize;
  168.             strcpy( scan->f_fname, examine.d_fname );
  169.             ++ scan;
  170.         }
  171.  
  172.     qsort( list, length, sizeof (FILEINFO), dir_comp );
  173.  
  174.     free( globname );
  175.     Fsetdta( old_dta );
  176.  
  177.     return list;
  178. }
  179.  
  180. /*
  181.  *----------------------------------------------------------------------------
  182.  *
  183.  *  copy a file from `from' to `to_path\to_name', in a careful way.
  184.  *
  185.  *----------------------------------------------------------------------------
  186.  */
  187.  
  188. char * copy_file( from, to_path, to_name )
  189.     char            * from;
  190.     char            * to_path;
  191.     char            * to_name;
  192.     {
  193.     DMABUFFER       * old_dta   = (DMABUFFER *) Fgetdta();
  194.     char            * to        = dircat( to_path, to_name );
  195.     char            * tmp       = dircat( to_path, "$$$$$$$$.$$$" );
  196.     char            * ret_msg   = NULLPTR;
  197.  
  198.     struct stat     stat_from;
  199.     struct stat     stat_to;
  200.  
  201.     int             from_h      = -1;
  202.     int             to_h        = -1;
  203.     int             dest_exists;
  204.     long            chunk;
  205.     int             timestamp[ 2 ];
  206.  
  207.     if ( v_flag )
  208.     fprintf( stderr, "\t%s ==> %s\n", from, to );
  209.  
  210.     /* check existence & modes of source                                    */
  211.     if ( stat( from, & stat_from ) == NODEV ) {
  212.         ret_msg = "can't stat source";
  213.         goto exit;
  214.     }
  215.  
  216.     /* check existence & type of destination                                */
  217.     if ( dest_exists = ( stat( to, & stat_to ) != NODEV ) ) {
  218.         if ( stat_to.st_mtime > stat_from.st_mtime ) {
  219.             ret_msg = "source older than destination";
  220.             goto exit;
  221.         } else if ( ( stat_to.st_mode & S_IJDIR ) != 0 ) {
  222.             ret_msg = "destination is directory";
  223.             goto exit;
  224.         }
  225.     }
  226.  
  227.     /* open source file for reading                                         */
  228.     from_h = Fopen( from, 0 );
  229.     if ( from_h < 0 ) {
  230.         ret_msg = "can't open input file";
  231.         goto exit;
  232.     }
  233.  
  234.     /* create the temporary output file                                     */
  235.     to_h = Fcreate( tmp, stat_from.st_mode );
  236.     if ( to_h < 0 ) {
  237.         ret_msg = "can't create temp file";
  238.         goto exit;
  239.     }
  240.  
  241.     /* copy file contents across                                            */
  242.     Fsetdta( track_buffer );
  243.     while ( stat_from.st_size > 0 ) {
  244.         chunk = stat_from.st_size > BUFFER_SIZE ?
  245.         BUFFER_SIZE : stat_from.st_size;
  246.  
  247.         if ( chunk !=